package com.wn.aop;

import com.wn.dao.EmpDao;
import com.wn.dao.LogDao;
import com.wn.entity.Emp;
import com.wn.entity.Log;
import com.wn.utils.JwtUtil;
import com.wn.utils.SystemControllerLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


//切面类 日志 aop实现
@Aspect
@Component
public class LogAspect {

    @Resource
    private LogDao logDao;
    @Resource
    private EmpDao empDao;

    private String userName;              //用户名
    private String roleSign;              //角色
    private String requestPath;           //访问地址
    private Map<?,?> inputParamMap;       //传入参数
    private Map<String, Object> outputParamMap;//输入的结果
    private long startTimeMillis = 0;     //开始时间
    private long endTimeMillis = 0;       //结束时间
    private String discription;           //方法的描述
    private String remoteAddr;            //ip地址

    //切入点，拦截cotroller层方法
    @Pointcut("@annotation(com.wn.utils.SystemControllerLog)")
    public void controllerAspect(){
    }

    //记录开始时间，方法执行前执行
    @Before("execution(* com.wn.controller..*.*(..))")
    public void beforeOpration(){
        startTimeMillis = System.currentTimeMillis();

    }

    //记录结束时间，方法执行后执行
    @After("controllerAspect()")
    public void afterOpration(JoinPoint joinPoint){
        endTimeMillis = System.currentTimeMillis();
        discription = getControllerMethodDescription(joinPoint);
        //获取请求参数中的token
        String token  = (String) joinPoint.getArgs()[1];
        userName = JwtUtil.parseToken(token).get("id").asString();
        //拿到当前对象的角色标记
        roleSign = JwtUtil.parseToken(token).get("roleSign").asString();


        //执行生成日志
        this.insertLog();
    }

    //环绕触发
    @Around("execution(* com.wn.controller..*.*(..))")
    public Object aroundOparation(ProceedingJoinPoint pjp)throws Throwable{
        /**
         * 1.获取request信息
         * 获取用户登录的信息
         * */
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();

        ServletRequestAttributes sra = (ServletRequestAttributes) ra;

        HttpServletRequest request = sra.getRequest();
        //获取ip地址
        remoteAddr = request.getRemoteAddr();
        //获取传入参数
        inputParamMap=request.getParameterMap();
        //获取访问地址
        requestPath = request.getRequestURI();

        outputParamMap= new HashMap<>();


        //执行方法
        Object result = pjp.proceed();
        outputParamMap.put("result",result);
        return result;

    }

    //获取controller层注解中对方法的描述信息
    public static String getControllerMethodDescription(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SystemControllerLog annotation = method.getAnnotation(SystemControllerLog.class);
        String discription = annotation.description();
        return discription;
    }

    //输出日志
    private void insertLog(){
        Date date1 = new Date(startTimeMillis);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format1 = sdf.format(date1);
        Date date2 = new Date(endTimeMillis);

        Log log = new Log();
        log.setStarttime(date1);
        log.setEndtime(date2);
        log.setOpration(discription);
        log.setRequestpath(requestPath);
        log.setRemoteaddr(remoteAddr);
        log.setRolesign(roleSign);
        log.setUserid(userName);
        try{
            System.out.println(userName);
            Emp emp = empDao.queryById(userName);

            log.setUsername(emp.getEmpname());
        }catch (Exception e){
            log.setUsername("游客");
            e.printStackTrace();
        }


        logDao.insert(log);
    }


}
